﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using BlobTowerDefense.Game_Entities;
using BlobTowerDefense.Tools;

namespace BlobTowerDefense.Managers
{
    public enum TOWERTYPE { buildingPlace, tower1, tower2, tower3, tower4, tower5, tower6 };
    public enum TOWERSPECIAL { none, fast, strong, poison, ice, range }

    public struct TowerStats
    {
        public TOWERTYPE TowerType;
        public int Damage;
        public float Speed;
        public float Range;
        public int Cost;
        public int UpgradeCost;
        public TOWERSPECIAL Special;
        public string pathToModel;

        public int UpgradedDamage;
        public float UpgradedSpeed;
        public float UpgradedRange;

        public bool IsUpgraded;

        public TowerStats(TOWERTYPE towerType, int damage, float speed, float range, int upgradedDamage, float upgradedSpeed, float upgradedRange, bool isUpgraded, int cost, int upgradeCost, TOWERSPECIAL special, string pathToModel)
        {
            this.TowerType = towerType;
            this.Damage = damage;
            this.Speed = speed;
            this.Range = range;
            this.Cost = cost;
            this.UpgradeCost = upgradeCost;
            this.Special = special;
            this.pathToModel = pathToModel;

            this.UpgradedDamage = upgradedDamage;
            this.UpgradedSpeed = upgradedSpeed;
            this.UpgradedRange = upgradedRange;

            this.IsUpgraded = isUpgraded;
        }
    }

    public class TowerManager
    {
        private const int TOWERNUMBER = 7;

        public static Dictionary<TOWERTYPE, TowerStats> DefaultTowerStats = new Dictionary<TOWERTYPE,TowerStats>(TOWERNUMBER)
        {
           { TOWERTYPE.buildingPlace, new TowerStats(TOWERTYPE.tower1, 0, 0.0f, 0.0f, 0, 0.0f, 0.0f, false, 0, 0, TOWERSPECIAL.none, "Models/buildingPlace") },
           { TOWERTYPE.tower1, new TowerStats(TOWERTYPE.tower1, 30, 2.0f, 10.0f, 30, 2.0f, 15.0f, false, 200, 150, TOWERSPECIAL.none, "Models/Towers/tower1") },
           { TOWERTYPE.tower2, new TowerStats(TOWERTYPE.tower2, 40, 3.0f, 10.0f, 40, 4.0f, 15.0f, false, 400, 300, TOWERSPECIAL.fast, "Models/Towers/tower2") },
           { TOWERTYPE.tower3, new TowerStats(TOWERTYPE.tower3, 40, 2.0f, 10.0f, 50, 3.0f, 15.0f, false, 700, 500, TOWERSPECIAL.ice, "Models/Towers/tower3") },
           { TOWERTYPE.tower4, new TowerStats(TOWERTYPE.tower4, 50, 3.0f, 10.0f, 60, 3.0f, 15.0f, false, 1000, 500, TOWERSPECIAL.poison, "Models/Towers/tower4") },
           { TOWERTYPE.tower5, new TowerStats(TOWERTYPE.tower5, 70, 2.0f, 10.0f, 80, 2.0f, 15.0f, false, 1500, 1000, TOWERSPECIAL.strong, "Models/Towers/tower5") },
           { TOWERTYPE.tower6, new TowerStats(TOWERTYPE.tower6, 50, 2.5f, 20.0f, 50, 2.5f, 30.0f, false, 1500, 1000, TOWERSPECIAL.range, "Models/Towers/tower6") }
        };

        public static Dictionary<TOWERTYPE, List<Vector3>> defaultColor { get; private set; } //default color of towers in game

        public static List<Tower> Towers;

        public TowerManager()
        {
            Towers = new List<Tower>();
            defaultColor = new Dictionary<TOWERTYPE, List<Vector3>>();


            // Get default color of all towers in game
            Model model;
            for (TOWERTYPE type = TOWERTYPE.tower1; type <= TOWERTYPE.tower6; type++)
            {
                defaultColor[type] = new List<Vector3>();
                // Load model
                model = GamePage.content.Load<Model>(DefaultTowerStats[type].pathToModel);
                // Save all default model colors
                foreach (ModelMesh mesh in model.Meshes)
                {
                    foreach (BasicEffect effect in mesh.Effects)
                    {
                        defaultColor[type].Add(effect.DiffuseColor);
                    }
                }
                
            }
        }

        public void LoadTowers(Vector3[] towersPositions, Vector3[] towersScales)
        {
            for (int i = 0; i < towersPositions.Length; i++)
            {
                Towers.Add(new Tower(towersPositions[i], towersScales[i]));
            }
        }

        public void Update(EnemyManager enemyManager)
        {
            UpdateTowers(enemyManager);
        }

        private void UpdateTowers(EnemyManager enemyManager)
        {
            foreach (Tower tower in Towers)
            {
                if (enemyManager.Enemies.Count <= 0)
                {
                    tower.Update(null);
                }
                else
                {
                    foreach (EnemyEntity enemy in enemyManager.Enemies)
                    {
                        tower.Update(enemy);
                    }
                }
            }
        }

        public void Draw()
        {
            DrawTowers();
        }

        private void DrawTowers()
        {
            foreach (Tower tower in Towers)
            {
                if (tower.TowerType == TOWERTYPE.buildingPlace)
                {
                    if (CursorState.IsTowerSelected == true)
                    {
                        tower.Draw();
                    }
                }
                else
                {
                    if (CursorState.IsTowerSelected && (CursorState.TowerSelectedStats.TowerType == tower.TowerType))
                    {
                        tower.Emphasize = true;
                    }
                    else
                    {
                        tower.Emphasize = false;
                    }

                    tower.Draw();
                }
            }
        }

        public int? SelectTower(Ray cursorRay)
        {
            foreach (Tower tower in Towers)
            {
                if (tower.TowerType == TOWERTYPE.buildingPlace)
                {
                    if (RayIntersectsModel(cursorRay, tower, tower.Scale))
                    {
                        return Towers.IndexOf(tower);
                    }
                }
            }

            return null;
        }

        public void BuildTower(int? index)
        {
            if (index != null)
            {
                if (GamePage.PlayerMoney >= CursorState.TowerSelectedStats.Cost)
                {
                    GamePage.PlayerMoney -= CursorState.TowerSelectedStats.Cost;

                    Towers[(int)index].BuildTower(CursorState.TowerSelectedStats);
                }
            }
        }

        private bool RayIntersectsModel(Ray ray, Tower tower, Vector3 scale)
        {
            foreach (ModelMesh mesh in tower.Model.Meshes)
            {
                BoundingSphere sphere;

                if( tower.TowerType == TOWERTYPE.buildingPlace)
                    sphere = BoundingSphere_Tools.TransformBoundingSphere(mesh.BoundingSphere,
                        new Vector3(tower.position.X, tower.position.Y, tower.position.Z - 1.9f), scale.X);
                else
                    sphere = BoundingSphere_Tools.TransformBoundingSphere(mesh.BoundingSphere, tower.position, scale.X);

                if (ray.Intersects(sphere) != null)
                {
                    return true;
                }
            }
            return false;
        }

        public void UpgradeTowers()
        {
            if (GamePage.PlayerMoney >= CursorState.TowerSelectedStats.UpgradeCost)
            {
                GamePage.PlayerMoney -= CursorState.TowerSelectedStats.UpgradeCost;

                TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType] = new TowerStats(TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].TowerType,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].Damage,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].Speed,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].Range,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].UpgradedDamage,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].UpgradedSpeed,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].UpgradedRange,
                                                                            true,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].Cost,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].UpgradeCost,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].Special,
                                                                            TowerManager.DefaultTowerStats[CursorState.TowerSelectedStats.TowerType].pathToModel);

                foreach (Tower tower in Towers)
                {
                    if (tower.TowerType == CursorState.TowerSelectedStats.TowerType)
                    {
                        tower.Upgrade();
                    }
                }
            }
        }
    }
}
